package com.example.demo.widget.chart.pie

import android.graphics.Paint
import android.graphics.RectF
import android.util.Log
import com.example.demo.Logger
import com.example.demo.widget.chart.ChartItem
import com.example.demo.widget.chart.utils.MathUtils
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min
import kotlin.math.tan

/**
 * ChartComment帮助类
 *
 * @author wangheng
 */
class PieChartHelper2 {
    companion object {
        private const val TAG = "PieChartHelper"
    }
    var mCommentLineSize = 1f
    var mCenterX = 0f
    var mCenterY = 0f
    var mRadius = 0f
    var mChartSize = 0f
    var mCommentTopTextPaint: Paint? = null
    var mCommentTopTextPadding = 0f
    var mCommentBottomTextPaint: Paint? = null
    var mCommentBottomTextPadding = 0f
    var mList: ArrayList<ChartItem>? = null
    var mDrawRect = RectF()
    private val mInnerRect = RectF()

    fun calculateCommentInfo(){

        val list = mList
        if(list == null || list.isEmpty()){
            return
        }
        mInnerRect.left = mCenterX - mRadius
        mInnerRect.right = mCenterX + mRadius
        mInnerRect.top = mCenterY - mRadius
        mInnerRect.bottom = mCenterY + mRadius

        val size = list.size
        for(index in 0 until size){
            val item = list[index]
            // 计算在第几部分
            item.calculatePiePartInChart()
            // 得到圆上开始点
            getCommentStartPointInCircle(item)
            // 得到文字y轴位置
            getCommentContentLocation(list,index,item)
        }
    }

    private fun getCommentContentLocation(list: ArrayList<ChartItem>, index: Int, item: ChartItem) {
        val topTextLength = mCommentTopTextPaint?.measureText(item.title) ?: 0f
        val topTextSize = mCommentTopTextPaint?.textSize ?: 0f
        val bottomTextLength = mCommentBottomTextPaint?.measureText(item.subTitle) ?: 0f
        val bottomTextSize = mCommentBottomTextPaint?.textSize ?: 0f
        val halfLineSize = mCommentLineSize / 2f
        val maxTextLength = max(topTextLength,bottomTextLength)
        val part = item.partInChart
        if(index == 0){
            calculateFirstCommentContentLocation(list,index,item)
        }else{
            val preItem = list[index - 1]
            if(part == preItem.partInChart){
                if(part == ChartItem.PART_1){
                    val preBottom= preItem.subTitleRect.bottom + mCommentBottomTextPadding
                    var width = mDrawRect.right - maxTextLength - item.firstPoint.x
                    val angle = (item.startAngle + item.swipeAngle / 2f).toDouble()
                    val tan = tan(Math.toRadians(angle))
                    var height = width * tan
                    val delta = (item.firstPoint.y + height - 2 * mCommentTopTextPadding - halfLineSize - topTextSize) - preBottom

                    Logger.i(TAG,"first part,angle:$angle,height:$height,width:$width,delta:$delta")
                    if(delta < 0){
                        height -= delta
                        if(tan != 0.0){
                            width = abs((height / tan).toFloat())
                        }
                    }

                    var x = item.firstPoint.x + width
                    var y = (item.firstPoint.y + height).toFloat()

                    val deltaY = y + bottomTextSize + halfLineSize + 2 * mCommentBottomTextPadding - mDrawRect.bottom
                    if(deltaY > 0) {
                        y -= deltaY
                    }

                    val deltaX = x  - mInnerRect.right
                    if(deltaX < 0){
                        x = mDrawRect.right - maxTextLength
                    }

                    item.secondPoint.x = x
                    item.secondPoint.y = y

                    setOtherLocation(item,maxTextLength)
                    Logger.i(
                        TAG,"first part,angle:$angle(${item.firstPoint.x},${item.firstPoint.y})," +
                            "(${item.secondPoint.x},${item.secondPoint.y})," +
                            "(${item.thirdPoint.x},${item.thirdPoint.y})")
                }else{
                    val preTop = preItem.titleRect.top - mCommentTopTextPadding
                    var width = item.firstPoint.x - mDrawRect.left - maxTextLength
                    val angle = (item.startAngle + item.swipeAngle / 2 - 180).toDouble()
                    val tan = tan(Math.toRadians(angle))
                    var height = width * tan
                    val delta = (item.firstPoint.y - height + 2 * mCommentBottomTextPadding + bottomTextSize + halfLineSize) - preTop

                    Logger.i(TAG,"second part,angle:$angle,tan:$tan,height:$height,width:$width,delta:$delta")
                    if(delta > 0){
                        height -= delta
                        if(tan != 0.0){
                            width = abs((height / tan).toFloat())
                        }
                    }
                    item.secondPoint.x = item.firstPoint.x - width
                    item.secondPoint.y = (item.firstPoint.y - height).toFloat()
                    setOtherLocation(item,-maxTextLength)
                    Logger.i(
                        TAG,"second part,angle:$angle,width:$width,height:$height(${item.firstPoint.x},${item.firstPoint.y})," +
                            "(${item.secondPoint.x},${item.secondPoint.y})," +
                            "(${item.thirdPoint.x},${item.thirdPoint.y})")
                }
            }else{
                val bottomHeight = mCommentBottomTextPadding * 2 + bottomTextSize + halfLineSize
                var angle = item.startAngle + item.swipeAngle / 2f - 90
                if(angle < 45){
                    val radian = Math.toRadians(angle.toDouble())
                    var height = mDrawRect.bottom - bottomHeight - item.firstPoint.y
                    val tan = tan(radian)
                    var width = height * tan(radian).toFloat()
                    val widthDelta = mDrawRect.left - (item.firstPoint.x - (width + maxTextLength))

                    Logger.i(TAG,"not first ,part not same to pre,< 45,height:$height,width:$width,widthDelta:$widthDelta")
                    if(widthDelta > 0){ // 绘制区域已经在可绘制区域左边了
                        width -= widthDelta
                        if(tan != 0.0){
                            height = (width / tan).toFloat()
                        }
                    }

                    item.secondPoint.x = item.firstPoint.x - width
                    item.secondPoint.y = item.firstPoint.y + height
                    Logger.i(TAG,"(${item.firstPoint.x},${item.firstPoint.y}),(${item.secondPoint.x},${item.secondPoint.y})")
                }else { // 相当于if(angle < 90)的情况，实际上现在angle已经不可能大于90度了
                    angle = 90 - angle
                    val radian = Math.toRadians(angle.toDouble())
                    var width = item.firstPoint.x - (mDrawRect.left + maxTextLength)
                    val tan = tan(radian)
                    var height = (width * tan).toFloat()
                    val heightDelta = mDrawRect.bottom - height - bottomHeight - item.firstPoint.y

                    Logger.i(TAG,"not first ,part not same to pre,>= 45,height:$height,width:$width,heightDelta:$heightDelta")
                    if(heightDelta < 0){      // 绘制区域超过底部
                        height += heightDelta
                        if(tan != 0.0){
                            width = (height / tan).toFloat()
                        }
                    }
                    item.secondPoint.x = item.firstPoint.x - width
                    item.secondPoint.y = item.firstPoint.y + height
                }
                setOtherLocation(item,-maxTextLength)
            }
        }
    }

    private fun calculateFirstCommentContentLocation(list: ArrayList<ChartItem>, index: Int, item: ChartItem){
        val topTextLength = mCommentTopTextPaint?.measureText(item.title) ?: 0f
        val topTextSize = mCommentTopTextPaint?.textSize ?: 0f
        val bottomTextLength = mCommentBottomTextPaint?.measureText(item.subTitle) ?: 0f
        val bottomTextSize = mCommentBottomTextPaint?.textSize ?: 0f
        val halfLineSize = mCommentLineSize / 2f
        val maxTextLength = max(topTextLength,bottomTextLength)

        item.secondPoint.y = mDrawRect.top + topTextSize + mCommentTopTextPadding + halfLineSize

        val angle = 90 - if(list.size > 1){
            abs(item.startAngle + item.swipeAngle / 2)
        }else{
            0f
        }
        val radian = Math.toRadians(angle.toDouble())
        val delta = Math.abs(item.firstPoint.y - item.secondPoint.y)
        val tan = tan(radian)
        item.secondPoint.x = (item.firstPoint.x + delta * tan).toFloat()

        if(item.secondPoint.x + maxTextLength > mDrawRect.right){
            item.secondPoint.x = mDrawRect.right - maxTextLength
        }
        setOtherLocation(item,maxTextLength)
    }

    private fun setOtherLocation(item: ChartItem, deltaLength: Float) {
        val topTextLength = mCommentTopTextPaint?.measureText(item.title) ?: 0f
        val topTextSize = mCommentTopTextPaint?.textSize ?: 0f
        val bottomTextLength = mCommentBottomTextPaint?.measureText(item.subTitle) ?: 0f
        val bottomTextSize = mCommentBottomTextPaint?.textSize ?: 0f
        val halfLineSize = mCommentLineSize / 2f
        val maxTextLength = max(topTextLength,bottomTextLength)

        val x = item.secondPoint.x
        val y = item.secondPoint.y
        item.thirdPoint.x = x + deltaLength
        item.thirdPoint.y = y


        val rectLeftX = min(item.secondPoint.x,item.thirdPoint.x)

        item.titleRect.left = rectLeftX
        item.titleRect.top = y - halfLineSize - mCommentTopTextPadding - topTextSize
        item.titleRect.right = rectLeftX + maxTextLength
        item.titleRect.bottom = item.titleRect.top + topTextSize

        item.subTitleRect.left = rectLeftX
        item.subTitleRect.top = y + halfLineSize + mCommentBottomTextPadding
        item.subTitleRect.right = rectLeftX + maxTextLength
        item.subTitleRect.bottom = item.subTitleRect.top + bottomTextSize
    }

    private fun getItemCommentContentRect(item: ChartItem): RectF{
        val rect = RectF()
        rect.top = item.titleRect.top - mCommentTopTextPadding
        rect.left = item.secondPoint.x
        rect.right = item.thirdPoint.x
        rect.bottom = item.subTitleRect.bottom + mCommentBottomTextPadding
        return rect
    }

    private fun getCommentContentHeight(): Float{
        val topTextSize =  mCommentTopTextPaint?.textSize ?: 0f
        val bottomTextSize = mCommentBottomTextPaint?.textSize ?: 0f
        return mCommentTopTextPadding * 2 + mCommentBottomTextPadding + topTextSize + bottomTextSize + mCommentLineSize
    }

    // 得到圆上的开始点的坐标
    private fun getCommentStartPointInCircle(item: ChartItem) {
        val radius = mRadius + mChartSize / 2f
        val angle = item.startAngle + item.swipeAngle / 2f
        item.firstPoint = MathUtils.getPointF(
            mCenterX,
            mCenterY,
            radius,
            angle
        )
    }

    fun getPieTopHeight(leftRightSpaceSize: Float): Float{
        val list = mList
        if(list == null || list.size == 0){
            return 0f
        }
        var topRightCount = 0
        list.forEach {
            val angle = it.startAngle + it.swipeAngle / 2f
            Log.i(TAG,"startAngle:${it.startAngle},swipeAngle:${it.swipeAngle},angle:$angle")
            if(angle >= -90 && angle < -45){
                topRightCount++
            }
        }
        if(topRightCount > 0) {
            val topTextSize = mCommentTopTextPaint?.textSize ?: 0f
            val padding = mCommentBottomTextPadding * 2 + mCommentTopTextPadding * 2
            val bottomTextSize = mCommentBottomTextPaint?.textSize ?: 0f
            val lineSize = mCommentLineSize
            val topHeight = topTextSize + padding + bottomTextSize + lineSize
            // 加上最大高度
            return max(leftRightSpaceSize,topHeight)
        }
        return 0f
    }

    fun getPieBottomHeight(leftRightSpaceSize: Float): Float{
        val list = mList
        if(list == null || list.size <= 1){
            return 0f
        }
        list.forEach {
            val angle = it.startAngle + it.swipeAngle / 2f
            if(angle > 45 && angle < 135){
                return leftRightSpaceSize
            }
        }
        return 0f
    }

}